package com.hk.influx.dsl.functions.predicate;


import com.influxdb.client.domain.DeletePredicateRequest;

import javax.annotation.Nonnull;
import java.util.StringJoiner;
import java.util.stream.Stream;

/**
 * <pre>
 *
 * 对于 DeleteApi， {@link com.influxdb.client.DeleteApi#delete(DeletePredicateRequest, String, String)} 中，
 * {@link DeletePredicateRequest#predicate} 属性，官方API 并没有使用Bean 来构建这个语法，所以这里定义一个
 *
 *  Delete 中的 predicate的限制:
 *      1、不能为null，如果没有条件，此值要设置为空字符串 ""
 *      2、不支持正则表达式
 *      3、对于多条件，不支持OR 运算符，只能是 AND
 *      4、只能使用  =  或 !=
 *      5、可以使用 _measurement / _time / _value / tag / any column.
 *
 * <a href="https://docs.influxdata.com/influxdb/v2.0/reference/syntax/delete-predicate/" >官网文档</a>
 * </pre>
 *
 * @author Kevin
 */
public abstract class DeletePredicates {

    protected DeletePredicates() {
    }

    /**
     * AND 多条件
     */
    public static DeletePredicates and(DeletePredicates... predicates) {
        return new Logical("AND", predicates);
    }

    /**
     * _measurement
     */
    public static ColumnDeletePredicates measurement() {
        return new ColumnDeletePredicates("_measurement");
    }

    /**
     * time
     */
    public static ColumnDeletePredicates time() {
        return new ColumnDeletePredicates("_time");
    }

    /**
     * _value
     */
    public static ColumnDeletePredicates value() {
        return new ColumnDeletePredicates("_value");
    }

    public static ColumnDeletePredicates custom(String fieldName) {
        return new ColumnDeletePredicates(fieldName);
    }

    private static class Logical extends DeletePredicates {

        private final String operator;

        private final DeletePredicates[] predicates;

        Logical(@Nonnull final String operator, @Nonnull final DeletePredicates... predicates) {
            super();
            this.operator = operator;
            this.predicates = predicates;
        }

        @Override
        public String toString() {
            return Stream.of(predicates)
                    .map(Object::toString)
                    .filter(it -> it != null && !it.isEmpty())
                    .collect(() -> new StringJoiner(STR." \{operator} ", "(", ")")
                                    .setEmptyValue(""),
                            StringJoiner::add,
                            StringJoiner::merge)
                    .toString();
        }
    }
}
